home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Communication / Conference / Source / Controller.m < prev    next >
Text File  |  1993-01-19  |  20KB  |  852 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "Controller.h"
  5.  
  6. #import <stdio.h>
  7. #import <syscall.h>
  8. #import <pwd.h>
  9. #import <strings.h>
  10. #import <sys/types.h>
  11. #import <netdb.h>
  12. #import <signal.h>
  13. #import <defaults.h>
  14. #import <objc/Storage.h>
  15. #import <soundkit/Sound.h>
  16.  
  17.  
  18. @implementation Controller
  19.  
  20. void killCr(char *c, int len)
  21. {
  22.     int i;
  23.     
  24.     for(i=0;((i<len) && (c[i]!='\0'));i++)
  25.     if (c[i] == '\n')
  26.         c[i] = '\0';
  27.     return;
  28. }
  29.  
  30. int membercmp(MemberRecord *r1, MemberRecord *r2)
  31. {
  32.     return ((!strncmp(r1->user,r2->user,STRING_LENGTH)) &&
  33.         (!strncmp(r1->username,r2->username,STRING_LENGTH)) &&
  34.         (!strncmp(r1->machine,r2->machine,STRING_LENGTH)));
  35. }
  36.  
  37. void copymember(MemberRecord *r1, MemberRecord *r2)
  38. {
  39.     strncpy(r1->user,r2->user,STRING_LENGTH);
  40.     strncpy(r1->username,r2->username,STRING_LENGTH);
  41.     strncpy(r1->machine,r2->machine,STRING_LENGTH);
  42.     r1->port = r2->port;
  43.     return;
  44. }
  45.  
  46. DPSTimedEntryProc networkEntryHandler(DPSTimedEntry num,
  47.                         double now, 
  48.                         char *userData)
  49. {
  50.     [(id)userData doNetworkTimedEntry:(id)userData];
  51.     return 0;
  52. }
  53.  
  54. DPSTimedEntryProc alarmEntryHandler(DPSTimedEntry num,
  55.                         double now, 
  56.                         char *userData)
  57. {
  58.     [(id)userData doAlarmTimedEntry:(id)userData];
  59.     return 0;
  60. }
  61.  
  62. - init
  63. {
  64.     [super init];
  65.     alertSound = nil;
  66.     numberAlarms = 0;
  67.     netTimedEntry = 0;
  68.     return self;
  69. }
  70.  
  71. - addMachineQuit:sender
  72. {
  73.     [NXApp abortModal];
  74.     return self;
  75. }
  76.  
  77. - addMachineOk:sender
  78. {
  79.     [NXApp stopModal];
  80.     return self;
  81. }
  82.  
  83. - fetchSound:sender
  84. {
  85.     id pan;
  86.     const char * const tps[2] = {"snd",NULL};
  87.     char str[STRING_LENGTH];
  88.     
  89.     pan = [OpenPanel new];
  90.     [pan allowMultipleFiles:NO];
  91.     
  92.     if ([pan runModalForTypes:tps]) {
  93.     if (alertSound)
  94.         [alertSound free];
  95.     strncpy(str,[pan filename],STRING_LENGTH);
  96.     if (str && str[0])
  97.         alertSound = [[Sound alloc] initFromSoundfile:str];
  98.     else
  99.         alertSound = nil;
  100.     [soundFileTextField setStringValue:str];
  101.     [self setDefaults:soundFileTextField];
  102.     }
  103.     return self;
  104. }
  105.  
  106. - doAlarmTimedEntry:sender
  107. {
  108.     if (numberAlarms < (MAXALARMS *2)) {
  109.     numberAlarms++;
  110.     [coverButton setState:(![coverButton state])];
  111.     } else {
  112.     numberAlarms = 0;
  113.     DPSRemoveTimedEntry(alarmTimedEntry);
  114.     [coverButton setState:NO];
  115.     }
  116.     return self;
  117. }
  118.  
  119. - handleAlarm
  120. {    
  121.     if ([noisyAlertSwitch state]) {
  122.     if (alertSound)
  123.         [alertSound play:self];
  124.     else
  125.         NXBeep();
  126.     }
  127.     if ([visualAlertSwitch state]) {
  128.     alarmTimedEntry=DPSAddTimedEntry(ALARMENTRYPERIOD,
  129.                     (DPSTimedEntryProc)alarmEntryHandler,
  130.                     (void *)self,
  131.                      30);
  132.     }
  133.     if ([activateOnAlertSwitch state]) {
  134.     if ([NXApp isHidden])
  135.         [NXApp unhide:self];
  136.     }
  137.     return self;
  138. }
  139.  
  140. - doOutput:(char *)msg withSender:(MemberRecord *)owner andBold:(BOOL)bold
  141. {
  142.     int l;
  143.     id p;
  144.     char str[STRING_LENGTH*3+10];
  145.     
  146.     [self getBrowserString:str fromMember:owner];
  147.     sprintf(str,"%s: ",str);
  148.     p = [logText docView];
  149.     l = [p textLength];
  150.     [p setSel:l :l];
  151.     [p replaceSel:str];
  152.     [p setSel:l :[p textLength]];
  153.     if (bold)
  154.     [p setSelFontStyle:NX_BOLD];
  155.     else
  156.     [p setSelFontStyle:NX_ITALIC];
  157.     l = [p textLength];
  158.     [p setSel:l :l];
  159.     [p replaceSel:msg];
  160.     l = [p textLength];
  161.     [p setSel:l :l];
  162.     [p replaceSel:"\n"];
  163.     l = [p textLength];
  164.     [p setSel:l :l];
  165.     return self;
  166. }
  167.  
  168. - input:sender
  169. {
  170.     id matrix;
  171.     int i,s;
  172.     MemberRecord *temp;
  173.     char str[1024];
  174.         
  175.     i = [sender textLength];
  176.     if (1024 < i)
  177.     i = 1024;
  178.     
  179.     [sender selectAll:self];
  180.     s = [sender getSubstring:str start:0 length:i];
  181.     [sender replaceSel:""];
  182.     str[s] = '\0';
  183.     
  184.     [self doOutput:str withSender:(&me) andBold:YES];
  185.     
  186.     matrix = [memberBrowser matrixInColumn:0];
  187.     
  188.     for(i=0;(i<[matrix cellCount]);i++) {
  189.     if ([[matrix cellAt:i :0] state]) {
  190.         temp = [memberStore elementAt:i];
  191.         [speak setSendPort:temp->port];
  192.         [speak sendMessage:str from:(char *)(&me) length:(sizeof(me))];
  193.     }
  194.     }
  195.     [sender selectText:self];
  196.     return self;
  197. }
  198.  
  199. - quit:sender
  200. {
  201.     int i;
  202.     MemberRecord *temp;
  203.     for(i=0;(i<[memberStore count]);i++) {
  204.     temp = [memberStore elementAt:i];
  205.     [speak setSendPort:temp->port];
  206.     [speak goodByeIAmLeaving:(char *)(&me) length:(sizeof(me))];
  207.     }
  208.     [memberStore free];
  209.     [listen removePort];
  210.     [listen free];
  211.     [speak free];
  212.     [NXApp terminate:self];
  213.     return self;
  214. }
  215.  
  216. - (BOOL)gotMemberWithMachine:(const char *)machine
  217. {
  218.     int i;
  219.     MemberRecord *temp;
  220.     for(i=0;(i<[memberStore count]);i++) {
  221.     temp = [memberStore elementAt:i];
  222.     if (!strncmp(temp->machine,machine,STRING_LENGTH))
  223.        return YES;
  224.     }
  225.     return NO;
  226. }
  227.  
  228. - (BOOL)gotMember:(MemberRecord *)mem
  229. {
  230.     int i;
  231.     MemberRecord *temp;
  232.     
  233.     for(i=0;(i<[memberStore count]);i++) {
  234.     temp = [memberStore elementAt:i];
  235.     if (membercmp(mem,temp))
  236.        return YES;
  237.     }
  238.     return NO;
  239. }
  240.  
  241. - changePref:sender
  242. {
  243.     [self setDefaults:sender];
  244.     return self;
  245. }
  246.  
  247. - getDefaults:sender
  248. {
  249.     const char *c;
  250.     
  251.     c = NXReadDefault([NXApp appName],"ShowLogin");
  252.     [loginSwitch setState:((c == NULL) || (!strncmp("YES",c,3)))];
  253.     c = NXReadDefault([NXApp appName],"ShowReal");
  254.     [realSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
  255.     c = NXReadDefault([NXApp appName],"ShowMachine");
  256.     [machineSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
  257.     c = NXReadDefault([NXApp appName],"UseConference");
  258.     [useConferenceSwitch setState:((c == NULL) || (!strncmp("YES",c,3)))];
  259.     c = NXReadDefault([NXApp appName],"UseNetwork");
  260.     [useNetworkSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
  261.     c = NXReadDefault([NXApp appName],"UseNoiseAlert");
  262.     [noisyAlertSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
  263.     c = NXReadDefault([NXApp appName],"UseVisualAlert");
  264.     [visualAlertSwitch setState:((c == NULL) || (!strncmp("YES",c,3)))];
  265.     c = NXReadDefault([NXApp appName],"ActivateOnAlert");
  266.     [activateOnAlertSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
  267.     c = NXReadDefault([NXApp appName],"SoundFile");
  268.     [soundFileTextField setStringValue:c];
  269.     
  270.     return self;
  271. }
  272.  
  273. - setDefaults:sender
  274. {
  275.     char str[10];
  276.     char param[20];
  277.     const char *c;
  278.     char strn[64];
  279.     
  280.     // Yes, in case you were wondering, this _is_ Evil, not to mention
  281.     // sloppy in the extreme.
  282.     
  283.     if (sender == loginSwitch)
  284.     strncpy(param,"ShowLogin",20);
  285.     else if (sender == realSwitch)
  286.     strncpy(param,"ShowReal",20);
  287.     else if (sender == machineSwitch)
  288.     strncpy(param,"ShowMachine",20);
  289.     else if (sender == useConferenceSwitch)
  290.     strncpy(param,"UseConference",20);
  291.     else if (sender == useNetworkSwitch)
  292.     strncpy(param,"UseNetwork",20);
  293.     else if (sender == noisyAlertSwitch)
  294.     strncpy(param,"UseNoiseAlert",20);
  295.     else if (sender == visualAlertSwitch)
  296.     strncpy(param,"UseVisualAlert",20);
  297.     else if (sender == activateOnAlertSwitch)
  298.     strncpy(param,"ActivateOnAlert",20);
  299.     else if (sender == soundFileTextField) {
  300.     NXWriteDefault([NXApp appName],"SoundFile",[sender stringValue]);
  301.     if (alertSound)
  302.          [alertSound free];
  303.     
  304.     c = [sender stringValue];
  305.     if (c && c[0]) {
  306.         strncpy(strn,c,64);
  307.         alertSound = [[Sound alloc] initFromSoundfile:str];
  308.     }
  309.     return self;
  310.     }
  311.     
  312.     if ([sender state])
  313.     strncpy(str,"YES",10);
  314.     else
  315.     strncpy(str,"NO",10);
  316.     NXWriteDefault([NXApp appName],param,str);
  317.     
  318.     if ((sender == useConferenceSwitch) && ([sender state]) &&
  319.     (NX_ALERTDEFAULT==NXRunAlertPanel("Hey!","Load .Conference File now?",
  320.                        "Ok","Cancel",NULL)))
  321.         [self doConferenceFile:self];
  322.     if ((sender == useNetworkSwitch) && ([sender state]) &&
  323.     (NX_ALERTDEFAULT==NXRunAlertPanel("Hey!","Scan network now?",
  324.                        "Ok","Cancel",NULL)))
  325.     [self doNetwork:self];
  326.     
  327.     [memberBrowser reloadColumn:0];
  328.     return self;
  329. }
  330.  
  331. - selectAllMembers:sender
  332. {
  333.     id p;
  334.     int i;
  335.     
  336.     p = [memberBrowser matrixInColumn:0];
  337.     
  338.     for(i=0;(i<[p cellCount]);i++) {
  339.     [p selectCellAt:i :0];
  340.     }
  341.     return self;
  342. }
  343.  
  344. - connectTo:(const char *)machine
  345. {
  346.     int s;
  347.     MemberRecord *temp;
  348.     int i;
  349.     port_t pt;
  350.     
  351.     if ((!machine) || (!machine[0]) || (machine[0] == '\0'))
  352.     return self;
  353.     for(i=0;(i<[memberStore count]);i++) {
  354.     temp = [memberStore elementAt:i];
  355.     if (!strncmp(machine,temp->machine,STRING_LENGTH))
  356.         return self;
  357.     }
  358.     
  359.     s=NXRunAlertPanel("Hey!",
  360.         "Attempt to connect to %s?",
  361.         "Connect","Do Not Connect",NULL,machine);
  362.     if (s == NX_ALERTDEFAULT) {
  363.     pt = NXPortNameLookup(APPNAME,machine);
  364.     if (PORT_NULL!=pt) {
  365.         [speak setSendPort:pt];
  366.         [speak helloIAm:(char *)(&me) length:(sizeof(me))];
  367.     }
  368.     }
  369.     return self;
  370. }
  371.  
  372. - disconnectFrom:(const char *)machine
  373. {
  374.     int s;
  375.     MemberRecord *temp;
  376.     int i;
  377.     
  378.     for(i=0;(i<[memberStore count]);i++) {
  379.     temp = [memberStore elementAt:i];
  380.     if (!strncmp(machine,temp->machine,STRING_LENGTH)) {
  381.         s = NXRunAlertPanel("Hey!",
  382.                 "Attempt to disconnect from %s?",
  383.                 "Disconnect","Stay Connected",NULL,machine);
  384.         if (s == NX_ALERTDEFAULT) {
  385.         [speak setSendPort:temp->port];
  386.         [speak goodByeIAmLeaving:(char *)&me length:sizeof(me)];
  387.         [memberStore removeAt:i];
  388.         return self;
  389.         }
  390.     }
  391.     }
  392.     return self;
  393. }
  394.  
  395. - connectMember:sender
  396. {
  397.     char c[STRING_LENGTH];
  398.     
  399.     [addMachinePanel makeKeyAndOrderFront:self];
  400.     [addMachineField selectText:self];
  401.  
  402.     if (NX_RUNABORTED == [NXApp runModalFor:addMachinePanel]) {
  403.     [addMachinePanel close];
  404.     return self;
  405.     }
  406.     
  407.     [addMachinePanel close];
  408.     strncpy(c,[addMachineField stringValue],STRING_LENGTH);
  409.     killCr(c,STRING_LENGTH);
  410.     [self connectTo:c];
  411.     [memberBrowser reloadColumn:0];
  412.     return self;
  413. }
  414.  
  415. - disconnectMember:sender
  416. {
  417.     id p;
  418.     int i;
  419.     char c[STRING_LENGTH];
  420.     MemberRecord *temp;
  421.     
  422.     c[0] = '\0';
  423.     p = [memberBrowser matrixInColumn:0];
  424.     
  425.     for(i=0;(i<[memberStore count]);i++) {    
  426.     temp = [memberStore elementAt:i];
  427.     if ([[p cellAt:i :0] state]) {
  428.         strncpy(c,temp->machine,STRING_LENGTH);
  429.         killCr(c,STRING_LENGTH);
  430.     }
  431.     }
  432.     if (c[0]) {
  433.     [self disconnectFrom:c];
  434.     }
  435.     [memberBrowser reloadColumn:0];
  436.     return self;
  437. }
  438.  
  439. - connectMachine:sender
  440. {
  441.     id p,q;
  442.     char c[STRING_LENGTH];
  443.     
  444.     p = machineBrowser;
  445.     
  446.     q = [[p matrixInColumn:[p selectedColumn]] selectedCell];
  447.     if (q == nil)
  448.     return self;
  449.     strncpy(c,[q stringValue],STRING_LENGTH);
  450.     
  451.     killCr(c,STRING_LENGTH);
  452.     [self connectTo:c];
  453.     [memberBrowser reloadColumn:0];
  454.     return self;
  455. }
  456.  
  457. - disconnectMachine:sender
  458. {
  459.     id p,q;
  460.     char c[STRING_LENGTH];
  461.     
  462.     p = machineBrowser;
  463.     
  464.     q = [[p matrixInColumn:[p selectedColumn]] selectedCell];
  465.     if (q == nil)
  466.     return self;
  467.     strncpy(c,[q stringValue],STRING_LENGTH);
  468.     
  469.     killCr(c,STRING_LENGTH);
  470.     [self disconnectFrom:c];
  471.     [memberBrowser reloadColumn:0];
  472.     return self;
  473. }
  474.  
  475. - addMachineToConferenceFile:(const char *)machine
  476. {
  477.     FILE *fd;
  478.     char str[STRING_LENGTH+30];
  479.     char lstr[STRING_LENGTH];
  480.     char *cont;
  481.     
  482.     sprintf(str,"%s/%s",homedir,".ConferenceMachines");
  483.     fd = fopen(str,"r");
  484.     if (fd != NULL) {
  485.     for(cont = fgets(lstr,STRING_LENGTH,fd);
  486.                     cont;
  487.         cont = fgets(lstr,STRING_LENGTH,fd)) {
  488.         killCr(lstr,STRING_LENGTH);
  489.         if (!strncmp(lstr,machine,STRING_LENGTH)) {
  490.         fclose(fd);
  491.         return self;
  492.         }
  493.     }
  494.     fclose(fd);
  495.     }
  496.     fd = fopen(str,"a");
  497.     if (fd != NULL) {
  498.     fputs(machine,fd);
  499.     fputc('\n',fd);
  500.     fclose(fd);
  501.     } else {
  502.     fd = fopen(str,"w");
  503.     if (fd != NULL) {
  504.         fputs(machine,fd);
  505.         fputc('\n',fd);
  506.         fclose(fd);
  507.     }
  508.     }
  509.     return self;
  510. }
  511.  
  512. - removeMachineFromConferenceFile:(const char *)machine
  513. {
  514.     FILE *fd;
  515.     char str[STRING_LENGTH+30];
  516.     char lstr[STRING_LENGTH];
  517.     int i;
  518.     char *cont;
  519.     char mach[STRING_LENGTH];
  520.     id tempStore;
  521.     
  522.     strncpy(mach,machine,STRING_LENGTH);
  523.     killCr(mach,STRING_LENGTH);
  524.     tempStore = [[Storage alloc] initCount:0
  525.                     elementSize:(sizeof(char) * STRING_LENGTH)
  526.                     description:MACHINESTORAGEDESCRIPTION];
  527.     sprintf(str,"%s/%s",homedir,".ConferenceMachines");
  528.     fd = fopen(str,"r");
  529.     if (fd != NULL) {
  530.     for(cont = fgets(lstr,STRING_LENGTH,fd);
  531.                         cont;
  532.         cont = fgets(lstr,STRING_LENGTH,fd)) {
  533.         killCr(lstr,STRING_LENGTH);
  534.         if (strncmp(lstr,mach,STRING_LENGTH)) {
  535.         [tempStore addElement:lstr];
  536.         }
  537.     }
  538.     fclose(fd);
  539.     }
  540.     fd = fopen(str,"w");
  541.     if (fd == NULL)
  542.     return self;
  543.     for(i=0;(i<[tempStore count]);i++) {
  544.     fputs([tempStore elementAt:i],fd);
  545.     fputc('\n',fd);
  546.     }
  547.     fclose(fd);
  548.     [tempStore free];
  549.     return self;
  550. }
  551.  
  552. - addMachine:sender
  553. {
  554.     char c[STRING_LENGTH];
  555.     
  556.     [addMachinePanel makeKeyAndOrderFront:self];
  557.     [addMachineField selectText:self];
  558.     
  559.     if (NX_RUNABORTED == [NXApp runModalFor:addMachinePanel]) {
  560.     [addMachinePanel close];
  561.     return self;
  562.     }
  563.     
  564.     [addMachinePanel close];
  565.     strncpy(c,[addMachineField stringValue],STRING_LENGTH);
  566.     killCr(c,STRING_LENGTH);
  567.     if (c[0]) {
  568.     [self addMachineToConferenceFile:c];
  569.     [machineBrowser reloadColumn:0];
  570.     if (strncmp(me.machine,c,STRING_LENGTH)) {
  571.         [self connectTo:c];
  572.         [memberBrowser reloadColumn:0];
  573.     }
  574.     }
  575.     return self;
  576. }
  577.  
  578. - removeMachine:sender
  579. {
  580.     id p,q;
  581.     char c[STRING_LENGTH];
  582.     
  583.     p = machineBrowser;
  584.     
  585.     q = [[p matrixInColumn:[p selectedColumn]] selectedCell];
  586.     if (q == nil)
  587.     return self;
  588.     strncpy(c,[q stringValue],STRING_LENGTH);
  589.     
  590.     killCr(c,STRING_LENGTH);
  591.     if (c && c[0]) {
  592.     [self removeMachineFromConferenceFile:c];
  593.     [machineBrowser reloadColumn:0];
  594.     if (strncmp(me.machine,c,STRING_LENGTH))
  595.         [self disconnectFrom:c];
  596.         [memberBrowser reloadColumn:0];
  597.     }
  598.     return self;
  599. }
  600.  
  601. - getBrowserString:(char *)str fromMember:(MemberRecord *)mem
  602. {
  603.     str[0] = '\0';
  604.     
  605.     if ([loginSwitch state]) {
  606.     sprintf(str,"%s",mem->user);
  607.     }
  608.     if ([realSwitch state]) {
  609.     if (str[0])
  610.         sprintf(str,"%s (%s)",str,mem->username);
  611.     else
  612.         sprintf(str,"(%s)",mem->username);
  613.     }
  614.     if ([machineSwitch state]) {
  615.     if (str[0])
  616.         sprintf(str,"%s@%s",str,mem->machine);
  617.     else
  618.         sprintf(str,"%s",mem->machine);
  619.     }
  620.     return self;
  621. }
  622.  
  623. - yeahRight:sender
  624. {
  625.     if (!strcmp([sender title],"Thomas K. Burkholder")) {
  626.     [sender setTitle:"Waddya want, a picture?"];
  627.     } else {
  628.     [sender setTitle:"Thomas K. Burkholder"];
  629.     }
  630.     return self;
  631. }
  632.  
  633. - doConferenceFile:sender
  634. {
  635.     char *cont;
  636.     port_t pt;
  637.     FILE *fd;
  638.     char str[STRING_LENGTH+30];
  639.     sprintf(str,"%s/%s",homedir,".ConferenceMachines");
  640.     fd = fopen(str,"r");
  641.     if (fd == NULL)
  642.     return self;
  643.  
  644.     for(cont = fgets(str,STRING_LENGTH,fd);
  645.                     cont;
  646.     cont = fgets(str,STRING_LENGTH,fd)) {
  647.     killCr(str,STRING_LENGTH);
  648.     if ((![self gotMemberWithMachine:str]) &&
  649.        (strncmp("localhost",str,STRING_LENGTH)) &&
  650.        (strncmp("broadcasthost",str,STRING_LENGTH)) &&
  651.        (strncmp(me.machine,str,STRING_LENGTH))) {
  652.         pt = NXPortNameLookup(APPNAME,str);
  653.         if (PORT_NULL!=pt) {
  654.         [speak setSendPort:pt];
  655.         [speak helloIAm:(char *)(&me) length:(sizeof(me))];
  656.         }
  657.     }
  658.     }
  659.     return self;
  660. }
  661.  
  662. - doNetworkTimedEntry:sender
  663. {
  664.     port_t pt;
  665.     struct hostent *he;
  666.     
  667.     he = gethostent();
  668.     
  669.     if (he == NULL) {
  670.     DPSRemoveTimedEntry(netTimedEntry);
  671.     netTimedEntry = 0;
  672.     return self;
  673.     }
  674.     
  675.     if ((![self gotMemberWithMachine:he->h_name]) &&
  676.     (strncmp("localhost",he->h_name,STRING_LENGTH)) &&
  677.     (strncmp("broadcasthost",he->h_name,STRING_LENGTH)) &&
  678.     (strncmp(me.machine,he->h_name,STRING_LENGTH))) {
  679.     pt = NXPortNameLookup(APPNAME,he->h_name);
  680.     if (PORT_NULL!=pt) {
  681.         [speak setSendPort:pt];
  682.         [speak helloIAm:(char *)(&me) length:(sizeof(me))];
  683.     }
  684.     }
  685.     return self;
  686. }
  687.  
  688. - doNetwork:sender
  689. {
  690.     sethostent(1);    
  691.     if (!netTimedEntry)
  692.     netTimedEntry = DPSAddTimedEntry(NETWORKENTRYPERIOD,
  693.                      (DPSTimedEntryProc)networkEntryHandler,
  694.                      (void *)self,
  695.                      NX_BASETHRESHOLD);
  696.     return self;
  697. }
  698.  
  699. - appDidInit:sender
  700. {
  701.     struct passwd *pwent;
  702.     char str[64];
  703.     const char *c;
  704.     
  705.     [self getDefaults:sender];
  706.     
  707.     // Initialize sound alert
  708.     c = [soundFileTextField stringValue];
  709.     if (c && c[0]) {
  710.     strncpy(str,c,64);
  711.     alertSound = [[Sound alloc] initFromSoundfile:str];
  712.     }
  713.     
  714.     // Initialize visual alert
  715.     alertWindow = [NXApp appIcon];
  716.     [[alertWindow setContentView:coverButton] free];
  717.     
  718.     pwent = getpwuid(getuid());
  719.     
  720.     strncpy(homedir,pwent->pw_dir,STRING_LENGTH);
  721.     strncpy(me.user,pwent->pw_name,STRING_LENGTH);
  722.     sscanf(pwent->pw_gecos,"%[^,]",me.username);
  723.     gethostname(me.machine,STRING_LENGTH);
  724.     killCr(me.machine,STRING_LENGTH);
  725.  
  726.     memberStore = [[Storage alloc] initCount:0
  727.                     elementSize:(sizeof(MemberRecord))
  728.                     description:MEMBERSTORAGEDESCRIPTION];
  729.     speak = [[ConferenceSpeaker alloc] init];
  730.     listen = [[ConferenceListener alloc] init];
  731.     [listen setDelegate:self];
  732.     [listen checkInAs:APPNAME];
  733.     [listen addPort];
  734.     
  735.     if ([useConferenceSwitch state])
  736.     [self doConferenceFile:self];
  737.     [machineBrowser reloadColumn:0];
  738.     
  739.     if ([useNetworkSwitch state])
  740.     [self doNetwork:self];
  741.  
  742.     [memberBrowser reloadColumn:0];
  743.     
  744.     [[inputText docView] setDelegate:self];
  745.     [[inputText docView] setCharFilter:(NXCharFilterFunc)NXFieldFilter];
  746.     [[inputText window] makeKeyAndOrderFront:self];
  747.     [[inputText docView] selectAll:sender];
  748.     return self;
  749. }
  750.  
  751. -(int)browser:sender fillMatrix:matrix inColumn:(int)column
  752. {
  753.     id currentCell;
  754.     int i;
  755.     
  756.     if (sender == memberBrowser) {
  757.     MemberRecord *temp;
  758.     char l[STRING_LENGTH*3 + 10];
  759.     
  760.     for(i=0;(i<[memberStore count]);i++) {
  761.         [matrix addRow];
  762.         currentCell = [matrix cellAt:i :column];
  763.         temp = [memberStore elementAt:i];
  764.         [self getBrowserString:l fromMember:temp];
  765.         [currentCell setStringValue:l];
  766.         [currentCell setLeaf:YES];
  767.         [currentCell setLoaded:YES];
  768.         [currentCell setTag:i];
  769.     }
  770.     return i;
  771.     } else { // sender is machineBrowser
  772.     FILE *fd;
  773.     char str[STRING_LENGTH+30];
  774.     char lstr[STRING_LENGTH];
  775.     char *cont;
  776.     
  777.     sprintf(str,"%s/%s",homedir,".ConferenceMachines");
  778.     fd = fopen(str,"r");
  779.     if (fd == NULL)
  780.         return 0;
  781.     for(i = 0,cont = fgets(lstr,STRING_LENGTH,fd);
  782.                     cont;
  783.         cont = fgets(lstr,STRING_LENGTH,fd)) {
  784.         if (lstr && lstr[0] && (lstr[0] != '\n')) {
  785.             [matrix addRow];
  786.             currentCell = [matrix cellAt:i:0];
  787.             [currentCell setStringValue:lstr];
  788.             [currentCell setLeaf:YES];
  789.             [currentCell setLoaded:YES];
  790.             [currentCell setTag:i];
  791.             i++;
  792.         }
  793.     }
  794.     fclose(fd);
  795.     return i;
  796.     }
  797. }
  798.  
  799. - textDidEnd:sender endChar:(unsigned short)whyEnd
  800. {
  801.     if (whyEnd != 0)
  802.     [self input:sender];
  803.     return self;
  804. }
  805.  
  806. - (int)helloIAm:(char *)fr length:(int)len
  807. {
  808.     MemberRecord temp,*mr;
  809.     
  810.     mr = (MemberRecord *)fr;
  811.     
  812.     if ([self gotMember:mr])
  813.     return 0;
  814.     copymember(&temp,mr);
  815.     temp.port = NXPortNameLookup(APPNAME,mr->machine);
  816.     [memberStore addElement:&temp];
  817.     [speak setSendPort:temp.port];
  818.     [speak helloIAm:(char *)(&me) length:(sizeof(me))];
  819.     [memberBrowser reloadColumn:0];
  820.     return 0;
  821. }
  822.  
  823. - (int)goodByeIAmLeaving:(char *)fr length:(int)len
  824. {
  825.     int i;
  826.     MemberRecord *temp;
  827.     
  828.     for(i=0;(i<[memberStore count]);i++) {
  829.     temp = [memberStore elementAt:i];
  830.     if (membercmp((MemberRecord *)fr,temp)) {
  831.         [memberStore removeAt:i];
  832.     }
  833.     }
  834.     [memberBrowser reloadColumn:0];
  835.     return 0;
  836. }
  837.  
  838. - (int)sendMessage:(char *)msg from:(char *)fr length:(int)len
  839. {
  840.     id p;
  841.     
  842.     if ([NXApp isHidden]) {
  843.     [self handleAlarm];
  844.     }
  845.     [self doOutput:msg withSender:(MemberRecord *)fr andBold:NO];
  846.     p = [inputText docView];
  847.     [p setSel:[p textLength] :[p textLength]];
  848.     return 0;
  849. }
  850.  
  851. @end
  852.